//
//  EMSSkillPlannerParser.m
//  EVE Mac Suite
//
//  Created by Vadim Lozko on 5/7/09.
//  Copyright 2009  __Vadim__. All rights reserved.
//

#import "EMSSkillPlannerParser.h"
#import "EVEAPICoreDataController.h"
#import "EMSSkillPlannerTreeNode.h"
#import "EVECDSkillPlan.h"
#import "EVECDSkillPlanItem.h"
#import "EVECDSkill.h"
#import "EVECDLearnedGroup.h"
#import "EVECDLearnedSkill.h"
#import "EVECDSkillRequirement.h"
#import "EVECDCharacter.h"
#import "EMSSkillPlannerWindowController.h"

@interface EMSSkillPlannerParser (privateMethods)

-(BOOL)recursivelyCreateSkillPlanItemForNode:(EMSSkillPlannerTreeNode*)node;
-(void)createPlanItemForNode:(EMSSkillPlannerTreeNode*)node;
-(void)addToPlanSkillPlanItem:(EVECDSkillPlanItem*)item withRepresentativeNode:(EMSSkillPlannerTreeNode*)node;
-(BOOL)isValidDropPositionForItem:(EVECDSkillPlanItem*)item withRepresentativeNode:(EMSSkillPlannerTreeNode*)node;
-(EVECDSkillPlanItem*)skillPlanItemWithRepresentiveNode:(EMSSkillPlannerTreeNode*)node trainToLevel:(int)level;
-(void)incrementSubsequentPlanItemsFromPosition:(int)index;
-(void)decrementSubsequentPlanItemsFromPosition:(int)index;

@end



@implementation EMSSkillPlannerParser

-(BOOL)parseTree:(EMSSkillPlannerTreeNode*)tree atProposedRow:(int)row
{
	_proposedDropRow = row;
	return [self recursivelyCreateSkillPlanItemForNode:tree];
}

-(void)moveUpSkillPlanItem:(EVECDSkillPlanItem*)item withRepresentativeNode:(EMSSkillPlannerTreeNode*)node
{
	NSArray* items = [plannedSkillsArrayController arrangedObjects];
	EVECDSkillPlanItem* previousItem = [items objectAtIndex:([items indexOfObject:item] - 1)];
	if(item.learnedSkill == previousItem.learnedSkill)
	{
		return;
	}
	for(EVECDSkillRequirement* itemSkillRequirement in item.learnedSkill.skill.skillRequirements)
	{
		if([itemSkillRequirement.skill isEqual:previousItem.learnedSkill.skill] &&
			itemSkillRequirement.level.intValue >= previousItem.learnedSkill.level.intValue)
		{
			return;
		}
	}
	item.position = previousItem.position;
	previousItem.position = [NSNumber numberWithInt:(previousItem.position.intValue + 1)];
}

-(void)deleteSkillPlanItem:(EVECDSkillPlanItem*)item withRepresentativeNode:(EMSSkillPlannerTreeNode*)node
{
	EVECDSkillPlan* skillPlan = item.partOfSkillPlan;
	[self decrementSubsequentPlanItemsFromPosition:(item.position.intValue - 1)];
	[skillPlan removeSkillPlanItemsObject:item];
	[EVECDContext deleteObject:item];
	NSArray* learningSkillNames = [NSArray arrayWithObjects:@"Analytical Mind", @"Clarity", @"Eidetic Memory", @"Empathy", @"Focus", 
								   @"Instant Recall", @"Iron Will", @"Learning", @"Logic", @"Presence", @"Spacial Awareness", nil];
	if([learningSkillNames containsObject:node.learnedSkill.skill.name])
	{
		[skillPlan recalculateTrainingTimes];
	}
	
}

@end

@implementation EMSSkillPlannerParser (privateMethods)

-(BOOL)recursivelyCreateSkillPlanItemForNode:(EMSSkillPlannerTreeNode*)node
{	
	TrainingStatus status = node.trainingStatus;
	if(status & trainingStatusLearnedEnough)
	{
		return NO;
	}
	for(EMSSkillPlannerTreeNode* childNode in node.childNodes)
	{ 
		[self recursivelyCreateSkillPlanItemForNode:childNode];
	}
	[self createPlanItemForNode:node];
	
	return YES;		
}

-(void)createPlanItemForNode:(EMSSkillPlannerTreeNode*)node
{
	int trainStartLevel = node.learnedSkill.level.intValue + 1, trainToLevel = node.level, i;
	for(i = trainStartLevel; i <= trainToLevel; i++)
	{
		NSPredicate* skillNamePredicate = [NSPredicate predicateWithFormat:@"learnedSkill.skill.name like %@", node.learnedSkill.skill.name];
		NSPredicate* levelPredicate = [NSPredicate predicateWithFormat:@"trainingToLevel == %@", [NSNumber numberWithInt:i]];
		NSPredicate* characterNamePredicate = [NSPredicate predicateWithFormat:@"partOfSkillPlan.planFor.name like %@", 
											   node.learnedSkill.partOfLearnedGroup.learnedBy.name];
		NSPredicate* existingPlanItemPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:
												  [NSArray arrayWithObjects:skillNamePredicate, levelPredicate, characterNamePredicate, nil]];
		EVECDSkillPlan* selectedSkillPlan = [[skillPlansArrayController selectedObjects] objectAtIndex:0];
		NSSet* existingPlanItemSet = [selectedSkillPlan.skillPlanItems filteredSetUsingPredicate:existingPlanItemPredicate];
		if([existingPlanItemSet count] == 0)
		{
			EVECDSkillPlanItem* newPlanItem = [NSEntityDescription insertNewObjectForEntityForName:@"EVECDSkillPlanItem" 
																		inManagedObjectContext:EVECDContext];
			newPlanItem.learnedSkill = node.learnedSkill;
			newPlanItem.trainingToLevel = [NSNumber numberWithInt:i];
			[self addToPlanSkillPlanItem:newPlanItem withRepresentativeNode:node];
		}
	}
}

-(void)addToPlanSkillPlanItem:(EVECDSkillPlanItem*)item withRepresentativeNode:(EMSSkillPlannerTreeNode*)node
{
	EVECDSkillPlan* selectedSkillPlan = [[skillPlansArrayController selectedObjects] objectAtIndex:0];

	while(![self isValidDropPositionForItem:item withRepresentativeNode:node])
	{
		_proposedDropRow++;
	}
	item.partOfSkillPlan = selectedSkillPlan;
	item.position = [NSNumber numberWithInt:0];
	int proposedPosition = _proposedDropRow + 1;
	[plannedSkillsArrayController rearrangeObjects];
	[self incrementSubsequentPlanItemsFromPosition:proposedPosition];
	item.position = [NSNumber numberWithInt:proposedPosition];
	_proposedDropRow++;

}

-(BOOL)isValidDropPositionForItem:(EVECDSkillPlanItem*)item withRepresentativeNode:(EMSSkillPlannerTreeNode*)node
{	
#ifdef DEBUG
	NSLog(@"Item skill: %@ Level: %@; Item Train to Level: %@; Node Train to Level: %i", 
		  item.learnedSkill.skill.name, item.learnedSkill.level, item.trainingToLevel, node.level);
#endif
	int learnedSkillLevel = item.learnedSkill.level.intValue;
	int itemTrainingToLevel = item.trainingToLevel.intValue;
	NSArray* antecedentItems = [[plannedSkillsArrayController arrangedObjects] subarrayWithRange:NSMakeRange(0, _proposedDropRow)];	
	if(item.learnedSkill.skillPointsLearned.intValue > 0)
	{
		if(itemTrainingToLevel - 1 == learnedSkillLevel)
		{
			return YES;
		} else {
			EVECDSkillPlanItem* previousTrainingToLevelItem = [self skillPlanItemWithRepresentiveNode:node trainToLevel:(itemTrainingToLevel - 1)];
			if(!previousTrainingToLevelItem)
			{
				NSLog(@"Lookup Error");
				return YES;
			}
			if([antecedentItems containsObject:previousTrainingToLevelItem])
			{
				return YES;
			} else {
				return NO;
			}
		}
	} else {
		if(itemTrainingToLevel == 1)
		{
			BOOL allTrainedEnough = YES;
			for(EMSSkillPlannerTreeNode* childNode in node.childNodes)
			{
				if(!(childNode.trainingStatus & trainingStatusLearnedEnough))
				{
					EVECDSkillPlanItem* requiredItem = [self skillPlanItemWithRepresentiveNode:childNode trainToLevel:childNode.level];
					if(!requiredItem)
					{
						allTrainedEnough = NO;
						break;
					}
					if([antecedentItems containsObject:requiredItem])
					{
						return YES;
					} else {
						return NO;
					}
				}
			}
			return allTrainedEnough;
		} else {
			EVECDSkillPlanItem* previousTrainingToLevelItem = [self skillPlanItemWithRepresentiveNode:node trainToLevel:(itemTrainingToLevel - 1)];
			if(!previousTrainingToLevelItem)
			{
				NSLog(@"Lookup Error");
				return YES;
			}
			if([antecedentItems containsObject:previousTrainingToLevelItem])
			{
				return YES;
			} else {
				return NO;
			}
		}
	}
}

-(EVECDSkillPlanItem*)skillPlanItemWithRepresentiveNode:(EMSSkillPlannerTreeNode*)node trainToLevel:(int)level
{
	NSArray* skillPlanItems = [plannedSkillsArrayController arrangedObjects];
	NSPredicate* trainToLevelPredicate = [NSPredicate predicateWithFormat:@"trainingToLevel == %@", [NSNumber numberWithInt:level]];
	NSPredicate* skillNamePredicate = [NSPredicate predicateWithFormat:@"learnedSkill.skill.name like %@", node.learnedSkill.skill.name];
	NSPredicate* plannedSkillItemPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:
											  [NSArray arrayWithObjects:trainToLevelPredicate, skillNamePredicate, nil]];
	NSArray* matchingPlannedSkillsArray = [skillPlanItems filteredArrayUsingPredicate:plannedSkillItemPredicate];
	if(!([matchingPlannedSkillsArray count] == 1))
	{
		return nil;
	} else {
		return ((EVECDSkillPlanItem*)[matchingPlannedSkillsArray objectAtIndex:0]);
	}
}

-(void)incrementSubsequentPlanItemsFromPosition:(int)index
{
	NSArray* items = [plannedSkillsArrayController arrangedObjects];
	int itemsCount = [items count];
	if(itemsCount == 0 || itemsCount == index)
	{
		return;
	} else {
		EVECDSkillPlanItem* item;
		while(item = [items objectAtIndex:index])
		{
			item.position = [NSNumber numberWithInt:(item.position.intValue + 1)];
			index++;
			if(item == [items lastObject])
			{
				return;
			}
		}
	}
}

-(void)decrementSubsequentPlanItemsFromPosition:(int)index
{
	NSArray* items = [plannedSkillsArrayController arrangedObjects];
	int itemsCount = [items count];
	if(itemsCount == 0 || itemsCount == index)
	{
		return;
	} else {
		EVECDSkillPlanItem* item;
		while(item = [items objectAtIndex:index])
		{
			item.position = [NSNumber numberWithInt:(item.position.intValue - 1)];
			index++;
			if(item == [items lastObject])
			{
				return;
			}
		}
	}
}

@end
